package com.example.demo.common.utils;

import com.aliyun.oss.HttpMethod;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.utils.IOUtils;
import com.aliyun.oss.internal.OSSConstants;
import com.aliyun.oss.internal.OSSUtils;
import com.aliyun.oss.model.GeneratePresignedUrlRequest;
import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.OSSObject;
import com.example.demo.information.entity.Student;
import com.example.demo.information.entity.info.StudentInfo;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONObject;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URL;
import java.net.URLEncoder;
import java.util.*;

public class PhotoOSSUtils {
    /**
     * 阿里云的oss存储相关参数
     * AccessKeyId = "LTAIobkrtuT2pLMQ";
     * AccessKeySecret = "tyDHX3NSjgSuPvTN4TKwBPyhw7mhNf";
     * Endpoint = "oss-cn-hangzhou.aliyuncs.com";
     * bucketName = "rongbo-paizhao";
     */
    private final String AccessKeyId = "LTAIobkrtuT2pLMQ";
    private final String AccessKeySecret = "tyDHX3NSjgSuPvTN4TKwBPyhw7mhNf";
    private final String Endpoint = "oss-cn-hangzhou.aliyuncs.com";
    private final String bucketName = "rongbo-paizhao";
    private OSS ossClientTemp = null;
    /*public void shutdown(){
        ossClient.shutdown();
    }*/

    public static void main(String[] args) {
        //String localFileName = "C:/Users/Administrator/Desktop/test.jpg";
        //String objectName = "test/2020/03/test.jpg";
        String objectName,localSaveFileName;
        PhotoOSSUtils oss = new PhotoOSSUtils();
        //上传文件
        /*String objectName = "default/defaultPhoto.jpg";
        String localFileName = "C:\\Users\\Administrator\\Desktop\\miss.jpg";
        oss.photoUpload(localFileName,objectName);*/
        //查看文件
        objectName = "29/2020/3/19/18dab7436f49a8ab87ed6d6a6e715410.jpg";
        localSaveFileName = "C:/test/"+objectName;
        oss.downFile(localSaveFileName,objectName);
        //oss.loadStuPhoto(objectName);
        //oss.urlLoadStuPhoto(objectName,);
        System.out.println(oss.urlLoadOneStuPhoto(objectName,"89","123",10));

        System.out.println("success-------");
    }

    /**
     * 文件上传
     * @param localFileName
     * @param yourObjectName
     */
    public void photoUpload(String localFileName,String yourObjectName){
        OSS ossClient = new OSSClientBuilder().build(Endpoint, AccessKeyId, AccessKeySecret);
        // 上传文件流。
        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream(localFileName);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        ossClient.putObject(bucketName, yourObjectName, inputStream);
        ossClient.shutdown();
    }

    /**
     * 文件上传2
     * @param inputStream
     * @param yourObjectName
     */
    public void photoUpload2(InputStream inputStream,String yourObjectName){
        OSS ossClient = new OSSClientBuilder().build(Endpoint, AccessKeyId, AccessKeySecret);
        ossClient.putObject(bucketName, yourObjectName, inputStream);
        ossClient.shutdown();
    }

    /**
     * 检测文件是否存在
     * @param yourObjectName
     * @return
     */
    public boolean checkFile(String yourObjectName){
        OSS ossClient = new OSSClientBuilder().build(Endpoint, AccessKeyId, AccessKeySecret);
        // 判断文件是否存在。doesObjectExist还有一个参数isOnlyInOSS，
        // 如果为true则忽略302重定向或镜像；如果为false，则考虑302重定向或镜像。
        boolean found = ossClient.doesObjectExist(bucketName, yourObjectName);
        //System.out.println(found);
        ossClient.shutdown();
        return found;
    }

    /**
     * 文件下载到本地
     * @param localSaveFileName 保存的绝对路径
     * @param objectName
     */
    public void downFile(String localSaveFileName,String objectName){
        OSS ossClient = new OSSClientBuilder().build(Endpoint, AccessKeyId, AccessKeySecret);
        // 下载OSS文件到本地文件。如果指定的本地文件存在会覆盖，不存在则新建。
        localSaveFileName = localSaveFileName.replaceAll("\\\\","/");
        createParentFolder(localSaveFileName);
        ossClient.getObject(new GetObjectRequest(bucketName, objectName), new File(localSaveFileName));
        ossClient.shutdown();
    }
    /**
     * 文件下载到本地
     * @param localSaveFileName 保存的绝对路径
     * @param objectName
     */
    private void downFileNoNewOss(String localSaveFileName,String objectName){
        // 下载OSS文件到本地文件。如果指定的本地文件存在会覆盖，不存在则新建。
        localSaveFileName = localSaveFileName.replaceAll("\\\\","/");
        createParentFolder(localSaveFileName);
        ossClientTemp.getObject(new GetObjectRequest(bucketName, objectName), new File(localSaveFileName));
    }
    /**
     * 根据objectName的路径创建保存路径
     * @param localParentPath 目录文件名
     * @param objectName
     */
    public void downFile2(String localParentPath,String objectName){
        String localSaveFileName = localParentPath+objectName;
        downFile(localSaveFileName,objectName);
    }
    /**
     * 判断当前的需要操作的文件地址的目录是否已经创建,并且创建
     * @param localSaveFileName
     */
    private void createParentFolder(String localSaveFileName){
        localSaveFileName = localSaveFileName.replaceAll("\\\\","/");
        if(localSaveFileName.lastIndexOf("/")!=-1){
            String localFolder = localSaveFileName.substring(0,localSaveFileName.lastIndexOf("/"));
            File file = new File(localFolder);
            if(!file.exists()){
                file.mkdirs();
            }
        }
    }

    /**
     * 学生照片保存
     * @param file input上传文件
     * @param fileSaveName
     * @param objectName
     * @param date
     * @return
     */
    public String uploadStuPhotoFile(MultipartFile file,String objectName,String fileSaveName,Date date,String localRoot) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        if (null == file) {return "error";}
        String myFileName = file.getOriginalFilename();// 文件原名称
        String ext = myFileName.substring(myFileName.lastIndexOf("."));
        objectName = objectName+cal.get(Calendar.YEAR)+"/"+cal.get(Calendar.MONTH)+"/"+cal.get(Calendar.DAY_OF_MONTH)+"/";
        objectName = objectName+MD5Tool.generateMD5ForString(fileSaveName)+ext;
        try {
            photoUpload2(file.getInputStream(),objectName);
        } catch (IOException e) {
            e.printStackTrace();
            return "error";
        }
        //本地存一份，用于后续调用
        String path = localRoot+objectName;
        createParentFolder(path);
        File localFile = new File(path);
        try {
            file.transferTo(localFile);
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return objectName;
    }

    /**
     * 学生照片保存（生成的证件照）
     * @param localPath 本地路径
     * @param objectName
     * @return
     */
    public void uploadStuPhotoByLocalPath(String localPath,String objectName){
        photoUpload(localPath,objectName);
    }

    private void init(){
        ossClientTemp = new OSSClientBuilder().build(Endpoint, AccessKeyId, AccessKeySecret);
    }
    private void shutdown(){
        ossClientTemp.shutdown();
    }

    /**
     * 获得图片的访问路径 获得一条url
     * @param objectName
     * @param width
     * @param height
     * @param ratio  百分比缩减
     * @param time
     * @return
     */
    private String urlLoadStuPhoto(String objectName,String width,String height,String ratio,Integer time){
        if(StringUtils.isBlank(ratio)){
            width = StringUtils.isBlank(width)?"89":width;
            height = StringUtils.isBlank(height)?"123":height;
        }
        time = time==null?10:time;
        String style;
        //String style = "image/resize,p_50";
        if(StringUtils.isNotBlank(width)&&StringUtils.isNotBlank(height)){
            style = "image/resize,m_lfit,w_"+width+",h_"+height;
        }else{
            ratio = StringUtils.isNotBlank(ratio)?ratio:"100";
            style = "image/resize,p_"+ratio;
        }
        System.out.println(style);
        // 指定过期时间为10分钟。
        Date expiration = new Date(new Date().getTime() + 1000 * 60 * time );
        GeneratePresignedUrlRequest req = new GeneratePresignedUrlRequest(bucketName, objectName, HttpMethod.GET);
        req.setExpiration(expiration);
        req.setProcess(style);
        URL signedUrl = ossClientTemp.generatePresignedUrl(req);
        //System.out.println(signedUrl);
        return signedUrl.toString();
    }

    /**
     * 获得图片的访问路径 获得一条url  图片长宽就是原来的图片长宽
     * @param objectName
     * @param time
     * @return
     */
    private String urlLoadStuPhotoByPhotoInfo(String objectName,Integer time){
        String style = "image/info";
        GetObjectRequest request = new GetObjectRequest(bucketName, objectName);
        request.setProcess(style);
        //set_accept_format
        OSSObject object = ossClientTemp.getObject(request);
        String jsonText = null;
        try {
            jsonText = IOUtils.readStreamAsString(object.getObjectContent(), OSSConstants.DEFAULT_CHARSET_NAME);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //解析JSON
        JSONObject jsonObjs = new JSONObject(jsonText);
        JSONObject imageHeight = (JSONObject) jsonObjs.get("ImageHeight");
        String height = (String) imageHeight.get("value");
        JSONObject imageWidth = (JSONObject) jsonObjs.get("ImageWidth");
        String width = (String) imageWidth.get("value");

        time = time==null?10:time;
        style = "image/resize,m_lfit,w_"+width+",h_"+height;
        //String style = "image/resize,p_50";
        // 指定过期时间为10分钟。
        Date expiration = new Date(new Date().getTime() + 1000 * 60 * time );
        GeneratePresignedUrlRequest req = new GeneratePresignedUrlRequest(bucketName, objectName, HttpMethod.GET);
        req.setExpiration(expiration);
        req.setProcess(style);
        URL signedUrl = ossClientTemp.generatePresignedUrl(req);
        return signedUrl.toString();
    }

    /**
     * 获得图片的访问路径 获得一条url  图片长宽就是原来的图片长宽
     * @param objectName
     * @param time
     * @return
     */
    private String urlLoadStuPhotoByPhotoInfoLimitMAX_W_H(String objectName,String maxWidth,String maxHeight,Integer time){
        String style = "image/info";
        GetObjectRequest request = new GetObjectRequest(bucketName, objectName);
        request.setProcess(style);
        //set_accept_format
        OSSObject object = ossClientTemp.getObject(request);
        String jsonText = null;
        try {
            jsonText = IOUtils.readStreamAsString(object.getObjectContent(), OSSConstants.DEFAULT_CHARSET_NAME);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //解析JSON
        JSONObject jsonObjs = new JSONObject(jsonText);
        JSONObject imageHeight = (JSONObject) jsonObjs.get("ImageHeight");
        String height = (String) imageHeight.get("value");
        JSONObject imageWidth = (JSONObject) jsonObjs.get("ImageWidth");
        String width = (String) imageWidth.get("value");

        float ratioW = Float.valueOf(maxWidth) / Float.valueOf(width);
        float ratioH = Float.valueOf(maxHeight) / Float.valueOf(height);
        float minRatio = Math.min(ratioW,ratioH);
        int newWidth = (int)(Float.valueOf(width) * minRatio);
        int newHeight = (int)(Float.valueOf(height) * minRatio);


        time = time==null?10:time;
        style = "image/resize,m_lfit,w_"+newWidth+",h_"+newHeight;
        //String style = "image/resize,p_50";
        // 指定过期时间为10分钟。
        Date expiration = new Date(new Date().getTime() + 1000 * 60 * time );
        GeneratePresignedUrlRequest req = new GeneratePresignedUrlRequest(bucketName, objectName, HttpMethod.GET);
        req.setExpiration(expiration);
        req.setProcess(style);
        URL signedUrl = ossClientTemp.generatePresignedUrl(req);
        return signedUrl.toString();
    }

    /**
     * 用于获得单个图片url  选择显示的图片长宽
     * @param objectName
     * @param width
     * @param height
     * @param time
     * @return
     */
    public String urlLoadOneStuPhoto(String objectName,String width,String height,int time){
        init();
        String url = urlLoadStuPhoto(objectName,width,height,null,time);
        shutdown();
        return url;
    }

    /**
     * 用于获得单个图片url  选择显示的图片比例
     * @param objectName
     * @param ratio
     * @param time
     * @return
     */
    public String urlLoadOneStuPhoto(String objectName,String ratio,int time){
        init();
        String url = urlLoadStuPhoto(objectName,null,null,ratio,time);
        shutdown();
        return url;
    }

    /**
     * 用于获得单个图片url   图片长宽就是原来的图片长宽
     * @param objectName
     * @param time
     * @return
     */
    public String urlLoadOneStuPhotoByInfo(String objectName,int time){
        init();
        String url = urlLoadStuPhotoByPhotoInfo(objectName,time);
        shutdown();
        return url;
    }

    /**
     * 用于获得单个图片url   图片长宽:按照原来的图片长宽根据最大的长宽等比缩放
     * @param objectName
     * @param time
     * @return
     */
    public String urlLoadOneStuPhotoByInfoLimitMAX(String objectName,String maxWidth,String maxHeight,int time){
        init();
        String url = urlLoadStuPhotoByPhotoInfoLimitMAX_W_H(objectName,maxWidth,maxHeight,time);
        shutdown();
        return url;
    }
    /**
     * 获得证件照的图片临时访问url
     * @param stuInfoList
     * @return
     */
    public List<StudentInfo> setPhotoUrl(List<StudentInfo> stuInfoList) {
        init();
        for(StudentInfo s : stuInfoList){
            String objectName = Constant.defaultPhotoObjectName;
            String ytObjectName = Constant.defaultPhotoObjectName;
            if(s.getAddress()!=null){
                objectName = s.getAddressStr();
                ytObjectName = StringUtils.isNotBlank(s.getYtAddressStr())?s.getYtAddressStr():ytObjectName;
            }
            String url = urlLoadStuPhoto(objectName,s.getWidth(),s.getHeight(),null,s.getUrlTime());
            s.setAddressUrl(url);
            String ytUrl = urlLoadStuPhoto(ytObjectName,null,null,"34",s.getUrlTime());
            s.setYtAddressUrl(ytUrl);
        }
        shutdown();
        return stuInfoList;
    }

    /**
     * 获得文件的输入流 inputStream
     * @param objectName
     */
    public void loadStuPhoto(String objectName){
        OSS ossClient = new OSSClientBuilder().build(Endpoint, AccessKeyId, AccessKeySecret);
        GetObjectRequest request = new GetObjectRequest(bucketName, objectName);
        // ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
        OSSObject ossObject = ossClient.getObject(bucketName, objectName);
        InputStream objectContent = ossObject.getObjectContent();
        ossClient.shutdown();


    }

    /**
     * 下载文件到本地地址
     * @param parentFolder 临时保存的文件夹
     * @param objecNameList
     * @return
     */
    public List<String> downObjectNameListToLocalList(String parentFolder,List<String> objecNameList) {
        List<String> localPathList = new ArrayList<>();
        init();
        for(String objectName : objecNameList){
            String localPathName = parentFolder+objectName;
            downFileNoNewOss(localPathName,objectName);
            localPathList.add(localPathName);
        }
        shutdown();
        return localPathList;
    }

    /**
     * 下载单张照片
     * @param objectName oss存储地址
     * @param fileName 文件名
     * @param response
     */
    public void downObjectName(String objectName,String fileName,HttpServletResponse response) throws IOException {
        if(!checkFile(objectName)){System.out.println("文件不存在");return;}
        String ext = objectName.substring(objectName.lastIndexOf("."));
        fileName = fileName+ext;
        OSS ossClient = new OSSClientBuilder().build(Endpoint, AccessKeyId, AccessKeySecret);
        GetObjectRequest request = new GetObjectRequest(bucketName, objectName);
        // ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
        OSSObject ossObject = ossClient.getObject(bucketName, objectName);
        InputStream in = ossObject.getObjectContent();
        response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
        OutputStream out = response.getOutputStream();
        byte buffer[] = new byte[1024];
        int len = 0;
        while((len=in.read(buffer))>0){
            out.write(buffer, 0, len);
        }
        in.close();
        out.close();
        ossClient.shutdown();
    }


    /*public String downLoadFile(String filetbid,String sfz,String objectName) throws IOException{
        HttpServletRequest request = ServletActionContext.getRequest();
        HttpServletResponse response = ServletActionContext.getResponse();
        FileRecord fileRecord = null;
        fileRecord = fileRecordDao.findByTbid(filetbid, objectName);
        //如果文件不存在
        if(fileRecord==null){
            System.out.println("第二次方案查找文件!");
            fileRecord = fileRecordDao.findBySfzObjectType(sfz,objectName);
        }
        if(fileRecord==null){
            request.setAttribute("message", "您要下载的资源已被删除！！");
            System.out.println("您要下载的资源已被删除！！");
            return "您要下载的资源已被删除！！";
        }

        String realname = sfz+"_";
        if(Constants.fileNameMap.containsKey(objectName)){
            String str = Constants.fileNameMap.get(objectName);
            if(StringUtils.isNotBlank(str)){
                realname += str;
            }else{
                realname += fileRecord.getUploadFileName().substring(0, fileRecord.getUploadFileName().lastIndexOf("."));
            }
        }else{
            realname = fileRecord.getUploadFileName().substring(0, fileRecord.getUploadFileName().lastIndexOf("."));
        }
        realname += "."+fileRecord.getFileExtName();
        response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(realname, "UTF-8"));
        FileInputStream in = new FileInputStream(fileRecord.getRealFilePath());
        OutputStream out = response.getOutputStream();
        byte buffer[] = new byte[1024];
        int len = 0;
        while((len=in.read(buffer))>0){
            out.write(buffer, 0, len);
        }
        in.close();
        out.close();
        return null;
    }*/
}
